package com.free.quartz.task;

import cn.hutool.http.HttpResponse;
import cn.hutool.http.HttpUtil;
import cn.hutool.json.JSONUtil;
import com.free.common.utils.StringUtils;
import com.free.common.utils.email.MailUtil;
import com.free.system.domain.FreeMember;
import com.free.system.domain.FreeMemberRecord;
import com.free.system.domain.pull.TicketGetReq;
import com.free.system.domain.pull.TicketQueryData;
import com.free.system.domain.pull.TicketQueryDataList;
import com.free.system.domain.pull.TicketQueryResp;
import com.free.system.mapper.FreeMemberMapper;
import com.free.system.mapper.FreeMemberRecordMapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.ZoneId;
import java.util.*;

/**
 * 定时任务调度测试
 *
 * @author Sophia
 */
@Slf4j
@Component("ryTask")
public class RyTask {

    @Autowired
    private MailUtil mailUtil;
    @Autowired
    private FreeMemberMapper freeMemberMapper;
    @Autowired
    private FreeMemberRecordMapper freeMemberRecordMapper;

    // 演示任务
    public void ryMultipleParams(String s, Boolean b, Long l, Double d, Integer i) {
        System.out.println(StringUtils.format("执行多参方法： 字符串类型{}，布尔类型{}，长整型{}，浮点型{}，整形{}", s, b, l, d, i));
    }

    public void ryParams(String params) {
        System.out.println("执行有参方法：" + params);
    }

    // 自定义任务
    /**
     * 定时刷新会员token
     */
    public void taskFreshMemberToken() {
        log.info("定时拉取token数据...");
        List<FreeMember> freeMembers = freeMemberMapper.selectFreeMemberList(null);
        if (freeMembers != null && freeMembers.size() > 0) {
            for (FreeMember freeMember : freeMembers) {
                log.info("会员{} 的token拉取中...", freeMember.getMemberPhone());
                queryTicketList(freeMember);
            }
        }
        log.info("所有会员token拉取成功...");
    }


    /**
     * 定时执行拉取票券数据
     *
     * @param phone      手机号
     * @param ticketName 票券名称
     * @param hour       小时
     * @param min        分钟
     */
    public void taskGetTicketByPhone(String phone, String ticketName, Integer hour, Integer min) {
        log.info("getTicketByPhone -----> 定时数据入参: {}, {}, {}, {}", phone, ticketName, hour, min);
        /**
         * 1.查询手机号对应的token信息
         * 2.根据手机号获取系统的票券信息，并封装成入参
         * 3.进入循环中，当时间到达时则开始抢票
         * 4.邮件通知票券领取结果
         */

        // 1.查询手机号对应的token信息
        FreeMember freeMember = freeMemberMapper.selectFreeMemberByPhone(phone);
        // 2.根据手机号获取系统的票券信息，并封装成入参
        List<TicketGetReq> ticketList = this.queryTicketList(freeMember);
        if (ticketList != null && ticketList.size() > 0) {
            for (TicketGetReq ticket : ticketList) {
                if (StringUtils.equals(ticket.getTicketName(), ticketName)) {
                    ticket.setHour(hour);
                    ticket.setMin(min);
                    ticket.setToken(freeMember.getToken());
                    ticket.setPhone(phone);
                    ticket.setEmail(freeMember.getMemberEmail());
                    // 3.进入循环中，当时间到达时则开始抢票
                    this.getTicketInfo(ticket);
                    break;
                }
            }
        }

    }

    /**
     * 获取所有可查询的券数据
     *
     * @param freeMember
     */
    public List<TicketGetReq> queryTicketList(FreeMember freeMember) {
        List<TicketGetReq> list = new ArrayList<>();
        String url = "https://cdfmbrapi.cdfg.com.cn/api/coupon/couCenter";
        Map<String, String> header = new HashMap<>();
        header.put("x-access-token", freeMember.getToken());
        String requestBody = String.format("{\"url\":\"%s\", \"header\":{\"x-access-token\":\"%s\"}}", url, freeMember.getToken());
        log.info("请求参数：{}", requestBody);

        HttpResponse resp = HttpUtil.createPost(url)
                .headerMap(header, true)
                .execute();
        log.info("获取所有票券信息：{}", resp);
        if (resp != null && resp.body() != null) {
            String body = resp.body();
            TicketQueryResp ticResp = JSONUtil.toBean(body, TicketQueryResp.class);
            if (ticResp != null && ticResp.getCode() == 1) {
                TicketQueryData data = ticResp.getData();
                List<TicketQueryDataList> ticketList = data.getData();
                for (TicketQueryDataList tickInfo : ticketList) {
                    log.info("查询到的券数据:{}", tickInfo);
                    TicketGetReq ticketGetReq = new TicketGetReq();
                    ticketGetReq.setTicketName(tickInfo.getCouTypeTitle());
                    ticketGetReq.setCode(tickInfo.getCode());
                    ticketGetReq.setActivityCode(tickInfo.getActivityCode());
                    ticketGetReq.setStoreOuCode(tickInfo.getStoreOuCode());
                    ticketGetReq.setStartTime(tickInfo.getStartTime());
                    ticketGetReq.setToken(freeMember.getToken());
                    list.add(ticketGetReq);
                }
            } else {
                if (StringUtils.containsAny(ticResp.getMsg(), "未登录", "登录失效", "重新登录")) {
                    log.info("检测到登录失效，则需要重新在系统中配置token...");
                    String mess = String.format("检测到会员%s配置的token认证权限已过期, 请重新配置，以防错误拉取票券时间...", freeMember.getMemberPhone());
                    log.info(mess);
                    String title = "<token认证过期>提醒";
                    mailUtil.sendMessage(freeMember.getMemberEmail(), title, mess);
                    log.info("token认证过期邮件提醒已发送成功!");
                }
            }
        }
        log.info("数据查询异常：{}", String.valueOf(resp));
        return list;
    }

    /**
     * 领取票券信息
     *
     * @param ticketGetReq 领取票券入参
     */
    public void getTicketInfo(TicketGetReq ticketGetReq) {
        FreeMemberRecord record = new FreeMemberRecord();
        record.setTicketName(ticketGetReq.getTicketName());
        record.setMemberPhone(ticketGetReq.getPhone());
        record.setRemark("抢票流程记录!");
        record.setPullResult("异常");
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
        StringBuilder message = new StringBuilder(String.format("会员%s 领取票券 %s \n", ticketGetReq.getPhone(), ticketGetReq.getTicketName()));

        try {
            // 设置时间为今天的10点
            LocalTime time = LocalTime.of(ticketGetReq.getHour(), ticketGetReq.getMin());
            LocalDate date = LocalDate.now(); // 获取今天的日期
            LocalDateTime localDateTime = LocalDateTime.of(date, time); // 组合日期和时间

            // 转换为UTC时间戳
            long getTicketTime = localDateTime.atZone(ZoneId.systemDefault()).toInstant().toEpochMilli();
            long currentTime = System.currentTimeMillis();
            log.info("判断是否到抢票券时间, 到则抢, 不到则等待....");
            log.info("抢票时间为: {}", sdf.format(getTicketTime));
            log.info("当前时间为: {}", sdf.format(currentTime));
            while (currentTime < getTicketTime) {
                try {
                    log.info("当前时间：{}", sdf.format(currentTime));
                    Thread.sleep(500); // 暂停0.5秒, 再判断是否到时间
                } catch (Exception e) {
                    log.error("睡眠0.5S出现异常: {}", e.getMessage());
                    log.error(e.getMessage(), e);
                }
                currentTime = System.currentTimeMillis(); // 更新当前时间
            }
            log.info("抢票时间已到，开始疯狂抢... {}", sdf.format(currentTime));
            record.setCreateTime(new Date());

            log.info("领取票券入参: {}", ticketGetReq);
            String url = "https://cdfmbrapi.cdfg.com.cn/api/coupon/getcou?activityCode=%s&code=%s&storeOuCode=%s&startTime=%s";
            Map<String, String> header = new HashMap<>();
            header.put("x-access-token", ticketGetReq.getToken());
            url = String.format(url,
                    ticketGetReq.getActivityCode(),
                    ticketGetReq.getCode(),
                    ticketGetReq.getStoreOuCode(),
                    ticketGetReq.getStartTime());
            log.info("请求路径为:{}", url);

            HttpResponse resp = HttpUtil.createPost(url)
                    .headerMap(header, true)
                    .execute();
            Date responseTime = new Date();
            record.setUpdateTime(responseTime);
            String responseTimeStr = sdf.format(responseTime);
            log.info("抢票响应信息：{}", resp);
            String mess = String.format("%s时, 票券《%s》 : ", responseTimeStr, ticketGetReq.getTicketName());
            if (resp != null && resp.body() != null) {
                String body = resp.body();
                TicketQueryResp ticResp = JSONUtil.toBean(body, TicketQueryResp.class);
                if (ticResp != null && ticResp.getCode() == 1) {
                    log.info("票券{} 领取成功!", ticketGetReq.getTicketName());
                    message.append(mess + "领取成功!");
                    record.setPullResult(mess + "领取成功!");
                } else {
                    log.info("票券{} 领取失败!", ticketGetReq.getTicketName());
                    message.append("error-------<领取失败>-------error");
                    message.append("\n失败响应：" + body);
                    record.setPullResult(mess + "领取失败!");
                }
            } else {
                message.append("领取请求失败：" + String.valueOf(resp));
                record.setPullResult(mess + "领取失败!");
            }

            String body = String.format("{\"url\":\"%s\", \"header\":{\"x-access-token\":\"%s\"}}", url, ticketGetReq.getToken());
            record.setRequestBody(body);
            record.setResponseBody(String.valueOf(resp));
        } catch (Exception e) {
            log.error("抢票券出现异常：{}", e.getMessage());
            log.error(e.getMessage(), e);
            message.append("抢票券时出现异常：" + e.getMessage() + "\n" + String.valueOf(e));
        } finally {
            freeMemberRecordMapper.insertFreeMemberRecord(record);
            String title = String.format("会员%s领取%s通知", ticketGetReq.getPhone(), ticketGetReq.getTicketName());
            mailUtil.sendMessage(ticketGetReq.getEmail(), title, message.toString());
            log.info("领取票券结果通知{} 邮件发送成功!", ticketGetReq.getEmail());
        }
    }

}
